/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.game.world;

import jinngine.math.Matrix4;
import jinngine.math.Vector3;
import space.debug.GlobalParameters;

/**
 *
 * @author Pierre
 */
public class WldLightCSMSlice {

    final double near;

    public double getNear() {
        return near;
    }
    final double far;
    final double center;
    final double radius;

    public WldLightCSMSlice(double near, double far, double center, double radius) {
        this.near = near;
        this.far = far;
        this.center = center;
        this.radius = radius;
    }

    /**
     *
     * @param inverseViewpoint
     * @param lightModification
     * @param textureSize
     * @return
     */
    public Matrix4 lightMatrix(Matrix4 inverseViewpoint, Matrix4 lightModification, final int textureSize) {
        //Sphere center in world's position
        final Vector3 c = inverseViewpoint.multiply(new Vector3(0, 0, -center));



        final double ir = 1. / radius;
        final Matrix4 lightMatrix = lightModification.inverse();


        // The center moves in a continuous way, which make the shadowmap unstable
        // in the world coordinate. When moving the camera, an ungly flickering
        // happends. Michal Valient sabilisation make the center move in a discrete
        // way so that shadowmap pixel position look stable.
        if (GlobalParameters.stabilizeShadowMap) {
            Matrix4.multiply(lightMatrix, c, c);
            c.x = (int) (c.x * ir * textureSize * .25);
            c.y = (int) (c.y * ir * textureSize * .25);
            c.z = (int) (c.z * ir * textureSize * .25);
            c.x *= radius / textureSize * 4.;
            c.y *= radius / textureSize * 4.;
            c.z *= radius / textureSize * 4.;
            Matrix4.multiply(lightModification, c, c);
        }
        final Matrix4 scale =
                new Matrix4(
                ir, 0., 0., 0.,
                0., ir, 0., 0.,
                0., 0., -ir, 0.,
                0., 0., 0., 1.);

        final Matrix4 translate =
                new Matrix4(
                1., 0., 0., -c.x,
                0., 1., 0., -c.y,
                0., 0., 1., -c.z,
                0., 0., 0., 1.);

        scale.assignMultiply(lightMatrix);
        scale.assignMultiply(translate);

        return scale;
    }

    @Override
    public String toString() {
        return "WldLightCSMSlice{" + "near=" + near + "far=" + far + "center=" + center + "radius=" + radius + '}';
    }
}
